<script setup lang="ts">
import {
  ref,
  Teleport,
  computed,
  reactive,
  useSlots,
  VNode,
  isVNode,
} from "vue";

import { ElButton, ElCard, ElTableColumn } from "element-plus";
import DrawerColumnFilter from "./DrawerColumnFilter.vue";
import Icon from "@/components/Icon.vue";

import { isString, merge, omit } from "lodash-es";
import { renderTemplate } from "@/utils";
import useDelay from "@/hooks/useDelay";

defineEmits<{
  refresh: []; // 刷新
}>();

type TColumnProps = Partial<
  (typeof ElTableColumn)["props"] & {
    hidden?: boolean;
    slot?: boolean | string;
    render?: (scope: any) => VNode;
  } & {}
>;

export type TProTable = {
  title?: string;
  // 列
  columns: TColumnProps[];

  // 数据列表
  list: any[];

  // 分页数据
  pagination?: any;

  // 数据加载状态
  loading?: boolean;
  // 是否悬浮
  footerFixed?: boolean | string;
  // 是否显示HeaderBar
  showHeaderBar?: boolean;

  showRefreshButton?: boolean;
  showColumnsButton?: boolean;

  // tableProps
  tableProps?: any;
  concise?: boolean;
  hiddenFooter?: boolean;
};

withDefaults(defineProps<TProTable>(), {
  showHeaderBar: true,
  showRefreshButton: true,
  showColumnsButton: true,
});

// 延迟状态
const [state] = useDelay({ mounted: true, autoRestore: true });

// 过滤 非 tableColumn 属性
const getTableColumnProps = (options: TProTable["columns"][0]) =>
  omit(options, ["render", "hidden", "slot"]);

// ---> S 处理列隐藏
// 弹窗状态
const visible = ref(false);

// 被隐藏数据列

// ----> S 处理ProTableMax 来的 slots
const slots = useSlots();

const slotsMap = computed<any>(() => {
  const slotsParents = slots.default?.()[0]["children"];
  return getScope(slotsParents)?.children;
});

// 递归找出最近的ProFormScope
const getScope = (nodes: any) => {
  if (nodes) {
    const scope = nodes[0];
    const scopeName = scope?.type?.name || scope?.type || scope?.type;

    if (isVNode(scope) && scopeName == "ProTableScope") {
      return scope;
    }

    return getScope(scope?.children);
  }
};

// <---- E

// 隐藏列数据
const hiddenMap = reactive(new Map());
</script>

<template>
  <div class="relative flex h-full flex-1 flex-col">
    <component
      :is="concise ? 'div' : ElCard"
      class="h-full w-full relative flex flex-1"
    >
   
      <template #header v-if="showHeaderBar">
        <div class="flex items-center">
          <slot name="title">
            <div class="text-lg font-500">{{ title }}</div>
          </slot>

          <div class="flex-auto text-right mx-3">
            <slot name="headerExtra" />
          </div>

          <div class="flex-none">
            <ElButton v-if="showRefreshButton" circle @click="$emit('refresh')">
              <Icon
                name="Refresh"
                v-loading="loading"
                style="--el-loading-spinner-size: 16px"
              />
            </ElButton>
            <ElButton v-if="showColumnsButton" circle @click="visible = true">
              <Icon name="Operation" />
            </ElButton>
          </div>
        </div>
      </template>

      <div class="absolute bottom-0 left-0 right-0 top-0 flex flex-col">
        <el-table
          v-bind="merge(tableProps, $attrs)"
          :data="list"
          v-loading="loading"
        >
          <template v-for="(item, index) in columns" :key="'title'">
            <ElTableColumn
              v-bind="getTableColumnProps(item)"
              v-if="!hiddenMap.get(item)"
            >
              <template
                v-if="item.renderNode || item.render || item.slot"
                v-slot="scope"
              >
                <component
                  v-if="item.renderNode"
                  :is="item.renderNode(scope.row, scope)"
                />

                <slot
                  v-else
                  :name="isString(item.slot) ? item.slot : item.prop"
                  :row="scope.row"
                  :index="scope.i"
                >
                  {{ renderTemplate(item.render, item)?.(scope.row, scope) }}
                </slot>

                <component
                  v-if="slotsMap"
                  :is="slotsMap[(isString(item.slot) ? item.slot : item.prop) as string]"
                  :row="scope.row"
                />
              </template>
            </ElTableColumn>
          </template>
        </el-table>
      </div>

      <!-- <component
        v-if="!hiddenFooter"
        :is="state && footerFixed ? Teleport : 'div'"
        :to="isString(footerFixed) ? footerFixed : '#containerFooter'"
      >
        <div
          class="flex-center"
          :class="footerFixed ? 'bg-white py-3 px-5' : 'mt-10'"
        >
          <div class="flex-auto">
            <slot name="footer" />
          </div>

          <el-pagination
            v-if="pagination"
            background
            size="medium"
            layout="prev, pager, next, total, sizes, jumpe"
            :total="pagination.total || 0"
            v-model:page-size="pagination.size"
            v-model:current-page="pagination.page"
          />
        </div>
      </component> -->
    </component>
  </div>

  <DrawerColumnFilter
    v-model="visible"
    :columns="columns"
    v-model:hiddenMap="hiddenMap"
  />
</template>
